半部电台
题目附件如下:
from random import choice
from Crypto.Util.number import bytes_to_long, long_to_bytes
with open('flag.txt', 'r') as file:
flag = file.read()
alphabet = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ ,.!?()\n'
IP = [58, 50, 42, 34, 26, 18, 10, 2,
60, 52, 44, 36, 28, 20, 12, 4,
62, 54, 46, 38, 30, 22, 14, 6,
64, 56, 48, 40, 32, 24, 16, 8,
57, 49, 41, 33, 25, 17, 9, 1,
59, 51, 43, 35, 27, 19, 11, 3,
61, 53, 45, 37, 29, 21, 13, 5,
63, 55, 47, 39, 31, 23, 15, 7
]
IP_inv = [IP.index(i)+1 for i in range(1,65)]
S1 = [14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7,
0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8,
4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0,
15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13
]
S2 = [15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10,
3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5,
0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15,
13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9
]
S3 = [10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8,
13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1,
13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7,
1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12
]
S4 = [7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15,
13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9,
10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4,
3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14
]
S5 = [2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9,
14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6,
4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14,
11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3
]
S6 = [12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11,
10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8,
9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6,
4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13
]
S7 = [4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1,
13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6,
1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2,
6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12
]
S8 = [13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7,
1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2,
7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8,
2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11
]
S = [S1, S2, S3, S4, S5, S6, S7, S8]
E = [32, 1, 2, 3, 4, 5, 4, 5,
6, 7, 8, 9, 8, 9, 10, 11,
12, 13, 12, 13, 14, 15, 16, 17,
16, 17, 18, 19, 20, 21, 20, 21,
22, 23, 24, 25, 24, 25, 26, 27,
28, 29, 28, 29, 30, 31, 32, 1
]
P = [16, 7, 20, 21, 29, 12, 28, 17,
1, 15, 23, 26, 5, 18, 31, 10,
2, 8, 24, 14, 32, 27, 3, 9,
19, 13, 30, 6, 22, 11, 4, 25
]
PC_1 = [57, 49, 41, 33, 25, 17, 9,
1, 58, 50, 42, 34, 26, 18,
10, 2, 59, 51, 43, 35, 27,
19, 11, 3, 60, 52, 44, 36,
63, 55, 47, 39, 31, 23, 15,
7, 62, 54, 46, 38, 30, 22,
14, 6, 61, 53, 45, 37, 29,
21, 13, 5, 28, 20, 12, 4
]
PC_2 = [14, 17, 11, 24, 1, 5, 3, 28,
15, 6, 21, 10, 23, 19, 12, 4,
26, 8, 16, 7, 27, 20, 13, 2,
41, 52, 31, 37, 47, 55, 30, 40,
51, 45, 33, 48, 44, 49, 39, 56,
34, 53, 46, 42, 50, 36, 29, 32
]
shift_num = [1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1]
def generate_key(ori_key):
key = bin(bytes_to_long(ori_key))[2:].zfill(64)
subkeys = []
temp = [key[i-1] for i in PC_1]
for i in shift_num:
temp[:28] = temp[:28][i:]+temp[:28][:i]
temp[28:] = temp[28:][i:]+temp[28:][:i]
subkeys.append(''.join(temp[j-1] for j in PC_2))
return subkeys
def encrypt(flag, subkey):
if isinstance(flag, str):
flag = flag.encode()
bin_flag = ''.join([bin(byte)[2:].zfill(8) for byte in flag])
padded_len = (64-(len(bin_flag) % 64)) % 64
padded_flag = bin_flag + '0'*padded_len
cate_text = [padded_flag[i*64:(i+1)*64] for i in range(0, len(padded_flag)//64)]
encrypted_text = ''
for text in cate_text:
t = ''.join(text[i-1] for i in IP)
L, R = t[:32], t[32:]
for cnt in range(2):
R_temp = R
k = subkey[cnt]
R_expanded = ''.join(R[i-1] for i in E)
R_xor = [str(int(R_expanded[i]) ^ int(k[i])) for i in range(48)]
R_groups = [R_xor[i:i+6] for i in range(0, 48, 6)]
res = ''
for i in range(8):
row = int(R_groups[i][0] + R_groups[i][5], base=2)
col = int(''.join(R_groups[i][1:5]), base=2)
int_res = S[i][16*row+col]
res += bin(int_res)[2:].zfill(4)
res_p = ''.join(res[i-1] for i in P)
new_R = ''.join(str(int(res_p[i]) ^ int(L[i])) for i in range(32))
R = new_R
L = R_temp
t = R + L
t = ''.join(t[i-1] for i in IP_inv)
encrypted_text += t
encrypted_bytes = b''
for i in range(0, len(encrypted_text), 8):
byte = int(encrypted_text[i:i + 8], 2)
encrypted_bytes += bytes([byte])
encrypted_text = encrypted_bytes
return encrypted_text
key = ''.join(choice(alphabet) for _ in range(8))
subkey = generate_key(key.encode())
text = ''.join(choice(alphabet) for _ in range(80))
en_text = encrypt(text, subkey)
en_flag = encrypt(flag, subkey)
print("Encrypted flag:", bytes_to_long(en_flag))
print("Random text:", bytes_to_long(text.encode()))
print("Encrypted random text:", bytes_to_long(en_text))
# Random text: 1433169670903900033290598508496811597458554347091908326167349539758187339135216972151914723453239468546083363706961226766115338958014353426202798099416062073054152456403680835925616718057857324
# Encrypted random text: 3851507203651627781457515888384520835461679330574698368154640790290686181615500129045283126272322650531408969672068137751730525857624960377061734950604811242261668405054878088817320921377495056
这个DES算法只进行了两轮,只有标准的16轮的八分之一,所以本题命名为 (半)^3部电台
虽然没有给密钥,但是给了一些随机的明密文对,因此思路是根据已知的明密文对恢复出密钥
至于怎么恢复密钥,由于轮数非常少,所以即使不用什么差分攻击、线性攻击等方法也可以做出来,这同时是因为DES算法所使用的 Feistel 结构每一轮只对一侧进行加密,混淆扩散的力度较小。(不过我也推荐大家尝试使用差分攻击、线性攻击等各种“标准”的攻击方式)

我们知道 DES 的主要结构如上图所示,
在第一轮里,
在第二轮里,
然后就自然想到暴力+统计了,但是不要对一整个密钥暴力,这样会时间复杂度爆炸的,而是分成8块对每一个S盒分别计算,从
解题代码如下:
from Crypto.Util.number import bytes_to_long, long_to_bytes
with open('encrypted_flag.txt', 'r') as f:
en_flag = f.read()
en_flag = long_to_bytes(int(en_flag))
text = 1733571697283962509488226713108269753699322498714010326656310076489877844089729148788129403124099930593602491145395337324365415309638864335256126266980930992016878248102013062728229825856295255
en_text = 3578059052586522474100389050030320588160089073371878413925896715373042626307922378489203525965322427489129100605094275877241918595390796602423805072859665451626477779012814084741966341775758398
texts = long_to_bytes(text).decode()
en_texts = long_to_bytes(en_text)
IP = [58, 50, 42, 34, 26, 18, 10, 2,
60, 52, 44, 36, 28, 20, 12, 4,
62, 54, 46, 38, 30, 22, 14, 6,
64, 56, 48, 40, 32, 24, 16, 8,
57, 49, 41, 33, 25, 17, 9, 1,
59, 51, 43, 35, 27, 19, 11, 3,
61, 53, 45, 37, 29, 21, 13, 5,
63, 55, 47, 39, 31, 23, 15, 7
]
IP_inv = [IP.index(i)+1 for i in range(1,65)]
S1 = [14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7,
0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8,
4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0,
15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13
]
S2 = [15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10,
3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5,
0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15,
13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9
]
S3 = [10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8,
13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1,
13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7,
1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12
]
S4 = [7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15,
13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9,
10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4,
3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14
]
S5 = [2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9,
14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6,
4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14,
11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3
]
S6 = [12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11,
10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8,
9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6,
4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13
]
S7 = [4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1,
13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6,
1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2,
6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12
]
S8 = [13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7,
1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2,
7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8,
2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11
]
S = [S1, S2, S3, S4, S5, S6, S7, S8]
E = [32, 1, 2, 3, 4, 5, 4, 5,
6, 7, 8, 9, 8, 9, 10, 11,
12, 13, 12, 13, 14, 15, 16, 17,
16, 17, 18, 19, 20, 21, 20, 21,
22, 23, 24, 25, 24, 25, 26, 27,
28, 29, 28, 29, 30, 31, 32, 1
]
P = [16, 7, 20, 21, 29, 12, 28, 17,
1, 15, 23, 26, 5, 18, 31, 10,
2, 8, 24, 14, 32, 27, 3, 9,
19, 13, 30, 6, 22, 11, 4, 25
]
PC_1 = [57, 49, 41, 33, 25, 17, 9,
1, 58, 50, 42, 34, 26, 18,
10, 2, 59, 51, 43, 35, 27,
19, 11, 3, 60, 52, 44, 36,
63, 55, 47, 39, 31, 23, 15,
7, 62, 54, 46, 38, 30, 22,
14, 6, 61, 53, 45, 37, 29,
21, 13, 5, 28, 20, 12, 4
]
PC_2 = [14, 17, 11, 24, 1, 5, 3, 28,
15, 6, 21, 10, 23, 19, 12, 4,
26, 8, 16, 7, 27, 20, 13, 2,
41, 52, 31, 37, 47, 55, 30, 40,
51, 45, 33, 48, 44, 49, 39, 56,
34, 53, 46, 42, 50, 36, 29, 32
]
shift_num = [1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1]
P_inv = [0] * 32
for idx, p_val in enumerate(P):
P_inv[p_val-1] = idx+1
def change(A, B):
return ''.join(A[i-1] for i in B)
def str_to_bin(s):
return ''.join(format(ord(c), '08b') for c in s)
def bytes_to_bin(b):
return ''.join(format(byte, '08b') for byte in b)
def bin_to_bytes(b):
return long_to_bytes(int(b, base=2))
def s_box_output(s_box_index, input_6bits):
row = int(input_6bits[0] + input_6bits[5], 2)
col = int(input_6bits[1:5], 2)
return format(S[s_box_index][16*row+col], '04b')
# 找出轮密钥k0和k1的可能值
def recover_round_keys(plain_blocks, cipher_blocks):
k1_candidates = [[] for _ in range(8)]
k0_candidates = [[] for _ in range(8)]
for i in range(len(plain_blocks)):
plain = plain_blocks[i]
cipher = cipher_blocks[i]
bin_plain = str_to_bin(plain)
bin_cipher = bytes_to_bin(cipher)
ip_plain = change(bin_plain, IP)
L0 = ip_plain[:32]
R0 = ip_plain[32:]
ip_cipher = change(bin_cipher, IP)
L2 = ip_cipher[32:] # IP置换后,前32位是R2,后32位是L2
R2 = ip_cipher[:32]
# 恢复k1
F_output_k1 = ''.join(str(int(R0[j]) ^ int(R2[j])) for j in range(32))
S_out_k1 = change(F_output_k1, P_inv)
E_R1 = change(L2, E)
# 对于每个S盒
for s_idx in range(8):
bits_e = E_R1[s_idx*6:(s_idx+1)*6]
int_e = int(bits_e, 2)
bits_s = S_out_k1[s_idx*4:(s_idx+1)*4]
int_s = int(bits_s, 2)
# 枚举k1_i的可能值
for k1_i in range(64):
s_input = int_e ^ k1_i
s_input_bin = format(s_input, '06b')
s_output = s_box_output(s_idx, s_input_bin)
if int(s_output, 2) == int_s:
k1_candidates[s_idx].append(k1_i)
# 恢复k0
F_output_k0 = ''.join(str(int(L0[j]) ^ int(L2[j])) for j in range(32))
S_out_k0 = change(F_output_k0, P_inv)
E_R0 = change(R0, E)
for s_idx in range(8):
bits_e0 = E_R0[s_idx*6:(s_idx+1)*6]
int_e0 = int(bits_e0, 2)
bits_s0 = S_out_k0[s_idx*4:(s_idx+1)*4]
int_s0 = int(bits_s0, 2)
for k0_i in range(64):
s_input0 = int_e0 ^ k0_i
s_input0_bin = format(s_input0, '06b')
s_output0 = s_box_output(s_idx, s_input0_bin)
if int(s_output0, 2) == int_s0:
k0_candidates[s_idx].append(k0_i)
# 对于每个S盒,选择出现次数最多的可能值作为k0_i和k1_i
k1 = []
for s_idx in range(8):
if k1_candidates[s_idx]:
best_candidate = max(set(k1_candidates[s_idx]), key=k1_candidates[s_idx].count)
k1.append(format(best_candidate, '06b'))
else:
k1.append('000000')
k1_str = ''.join(k1)
k0 = []
for s_idx in range(8):
if k0_candidates[s_idx]:
best_candidate = max(set(k0_candidates[s_idx]), key=k0_candidates[s_idx].count)
k0.append(format(best_candidate, '06b'))
else:
k0.append('000000')
k0_str = ''.join(k0)
return k0_str, k1_str
# 解密时直接使用原加密函数,只需要将密钥倒转一下(或者说对称一下)
def encrypt(flag, subkey):
if isinstance(flag, str):
flag = flag.encode()
bin_flag = ''.join([bin(byte)[2:].zfill(8) for byte in flag])
padded_len = (64-(len(bin_flag) % 64)) % 64
padded_flag = bin_flag + '0'*padded_len
cate_text = [padded_flag[i*64:(i+1)*64] for i in range(0, len(padded_flag)//64)]
encrypted_text = ''
for text in cate_text:
t = ''.join(text[i-1] for i in IP)
L, R = t[:32], t[32:]
for cnt in range(2):
R_temp = R
k = subkey[cnt]
R_expanded = ''.join(R[i-1] for i in E)
R_xor = [str(int(R_expanded[i]) ^ int(k[i])) for i in range(48)]
R_groups = [R_xor[i:i+6] for i in range(0, 48, 6)]
res = ''
for i in range(8):
row = int(R_groups[i][0] + R_groups[i][5], base=2)
col = int(''.join(R_groups[i][1:5]), base=2)
int_res = S[i][16*row+col]
res += bin(int_res)[2:].zfill(4)
res_p = ''.join(res[i-1] for i in P)
new_R = ''.join(str(int(res_p[i]) ^ int(L[i])) for i in range(32))
R = new_R
L = R_temp
t = R + L
t = ''.join(t[i-1] for i in IP_inv)
encrypted_text += t
encrypted_bytes = b''
for i in range(0, len(encrypted_text), 8):
byte = int(encrypted_text[i:i + 8], 2)
encrypted_bytes += bytes([byte])
encrypted_text = encrypted_bytes
return encrypted_text
# 把明密文对分组
plain_blocks = [texts[i:i+8] for i in range(0, len(texts), 8)]
cipher_blocks = [en_texts[i:i+8] for i in range(0, len(en_texts), 8)]
# 恢复轮密钥k0和k1
k0, k1 = recover_round_keys(plain_blocks, cipher_blocks)
subkey = []
subkey.append(k1)
subkey.append(k0)
print(encrypt(en_flag, subkey))
解得的伪flag:
Dear Alice,\n\nI hope this message finds you wel1. I\xe9\x88\xa5\xe6\xaa\x93 writing to tell you that I\xe9\x88\xa5\xe6\xaa\x9de been participating in Moectf recently ,\nit\xe9\x88\xa5\xe6\xaa\x9a a cybersecurity competition designed for students like you and me. The contest offers various tracks\nsuch as Web, Pwn, and morE.Based on my interest5, I chose the Crypto track.\nSince you\xe9\x88\xa5\xe6\xaa\x9de been my long-time partner in cryptology, I\xe9\x88\xa5\xe6\xaa\x93 sure you understand how much I wish our communication\ncould be free from the threats of cryptographic attackS. Every time we try to connect over the internet, it feels\nlike there\xe9\x88\xa5\xe6\xaa\x9a someone trying to steal our informatioN. How frustrating!\nThat\xe9\x88\xa5\xe6\xaa\x9a why I believe we should learn more about cryptography to better protect ourselves!. If you agree with my idea,\nplease include the flag hidden in this letter in your next replyy. If you\xe9\x88\xa5\xe6\xaa\x99e not sure what it is, try connecting all\nthe characters that come before dots in this letter into one lin3.\n\nLooking forward to hearing from you!\nYours,\nBob
可以看出,这是一篇英语小作文(误)
要解出真正的flag需要你仔细看这篇小作文的内容,直接交这么多字符肯定是不对的
最终得到的flag是 moectf{1eEkSN!y3}
之所以这样设计(整得像misc一样),是因为不希望大家做数学题做昏头了,把密码学的本质需求给忘了口牙!
(顺带一提,还真有提交这么多字符,自己还没意识到问题在哪的神人[DOGE])
你一定注意到了那些乱码吧,这是因为我刻意在明文里用了弯引号(智能引号),但是它们并不会影响你解出真正的
flag,只是起到一个混淆视听的效果
这篇小作文的内容是我自己撰写再用ai润色得到的,主要讲的是 Alice 和 Bob 久经密码学界的折磨,只要通信必被攻击(这个梗来自于:密码学相关的案例讲解中主人公几乎总是Alice和Bob),而解这道题的人在看完文章后可能也会察觉到自己不自知地变成了攻击他们的人。
希望有人能懂我的冷幽默.jpg
不过当然,其中也包含了我对于大家的希冀和勉励喵( •̀ ω •́ )✧
DES很适合作为你学习分组密码分析的起点,以后你可能会了解到更多的结构和算法,学会让人眼花缭乱的分析方法,比如高阶差分攻击、不可能差分攻击、截断差分攻击、差分-线性攻击、积分攻击等等,但它们的实现手段其实是相似的,都是通过利用明密文间某种高概率的数学性质来构造一个区分器,这个区分器就相当于一个筛子,把明显错误的那些密钥给筛掉,剩下的就是密钥的可能值。这个区分器构造得越精巧,筛掉的错误值就越多,最终暴力搜索的范围就越小。